//
// Created by zhuyijun on 2021/8/23.
//

#include <iostream>
#include "queue.h"
#include <cstdlib>
#include <ctime>

const int MIN_PER_HR = 60;

bool newCustomer(double x);

int main() {
    using std::cin;
    using std::cout;
    using std::endl;
    using std::ios_base;

    std::srand(std::time(0));
    cout << "Case Study: Bank of Heather Automatic Teller\n";
    cout << "Enter maximum size of queue: ";
    int qs;
    cin >> qs;
    Queue line(qs);
    cout << "Enter the number of simulation hours: ";
    int hours;
    cin >> hours;
    long cyclelimt = MIN_PER_HR * hours;
    cout << "Enter the average number of customer per hour: ";
    double perhour;
    cin >> perhour;
    double min_per_cust;
    min_per_cust = MIN_PER_HR;

    Item temp;
    long turnaways = 0;
    long customers = 0;
    long served = 0;
    long sum_line = 0;
    int wait_time = 0;
    long line_wait = 0;

    for (int cycle = 0; cycle < cyclelimt; ++cycle) {
        if (newCustomer(min_per_cust)) {
            if (line.isFull()) {
                turnaways++;
            } else {
                customers++;
                temp.set(cycle);
                line.enqueue(temp);
            }
        }
        if (wait_time <= 0 && !line.isEmpty()) {
            line.deQueue(temp);
            wait_time = temp.ptime();
            line_wait += cycle - temp.when();
            served++;
        }
        if (wait_time > 0) {
            wait_time--;
        }
        sum_line += line.queueCount();
    }
    if (customers > 0) {
        cout << "customers accepted: " << customers << endl;
        cout << "customers served: " << served << endl;
        cout << "       turnaways: " << turnaways << endl;
        cout.precision(2);
        cout.setf(ios_base::fixed, ios_base::floatfield);
        cout << (double) sum_line / cyclelimt << endl;
        cout << "average wait_time: " << (double) line_wait / served << endl;
    } else {
        cout << "No customers!\n";
    }
    return 0;
}

bool newCustomer(double x) {
    return (std::rand() * x / RAND_MAX < 1);
}